/******************

???̷߳?????

*******************/
#include <stdio.h>
#include <stdio.h>
#include <net/if.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <time.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <pthread.h>


#define BACKLOG    5   // 监听队列最大的数
#define SERV_PORT 5566
#define SERV_IP_ADDR "192.168.3.185"
#define QUIT "quit"

struct my_t{
	int newfd;
	struct sockaddr_in cin;
};

struct my_t info;

/*
线程调用函数的声明
功能：完成客户端和服务器端的通信
功能:struct my_t{
			int newfd;
			struct sockaddr_in cin;
}
*/
void cli_data_handle(void * arg);
/*服务器发送给当前客户端消息的函数
 *参数：发送消息的数组
 *返回值：无
 * */
void sendto_client(char *kbuf,struct my_t info);
/*******************************
 *功能：接受一次客户端的消息
 *参数：
 *     kbuf 传入一个buf，将接受的客户端信息填入进去
 *     info newfd and sockaddr_in cin 
 *返回值:无
 *******************************/
void recvto_client(char *buf,struct my_t cinfo);
int main(int argc, const char *argv[])
{
	int fd;

	//创建套接字
	fd = socket(AF_INET,SOCK_STREAM,0);
	if(fd <0){
	perror("socket");
	return -1;
	}
	
	//设置允许地址快速重用
	int b_reuse = 1;
	if(setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&b_reuse,
				sizeof(int))!=0){
		perror("setsockopt");
		return -1;
	}
	
	//地址信息结构提的申请和填写
	struct sockaddr_in sin;
	bzero(&sin,sizeof(sin));
	sin.sin_family = AF_INET;
	sin.sin_port = htons(SERV_PORT);
	sin.sin_addr.s_addr = INADDR_ANY;
	//表示绑定任意IP

	fprintf(stderr,"填充地址信息结构体成功\n");

	//地址信息结构体绑定
	 if (bind(fd,(struct sockaddr*)&sin,sizeof(sin))<0)
		{
			perror("bind");
			exit(2);
		}
	 fprintf(stderr, "绑定成功\n");
	 
	//监听listen 变为被动套接字
	
	if(listen(fd,BACKLOG)<0) {
		perror("listen");
		exit(4);
	 }

	 fprintf(stderr, "监听成功\n");

	//定义接受呵护端信息地址结构体
	struct sockaddr_in cin;
	socklen_t addrlen = sizeof(cin);
	
	int newfd = -1;
	pthread_t tid = -1;
	
	//进入循环
	 fprintf(stderr, "进入循环\n");
	while(1){
		newfd = accept(fd,(struct sockaddr*)&cin,
			&addrlen);
		if(newfd<0){
			perror("accept");
			break;
		}
		fprintf(stderr,"接受到%d连接成功\n",newfd);

	//填充结构体
	info.newfd = newfd;
	memcpy(&info.cin,&cin,sizeof(cin));
	

	//链接客户端的信息
	char ip[20]={};
	const char *np = inet_ntop(AF_INET,
		(void*)&cin.sin_addr.s_addr,ip,20);
	if(np == NULL){
		error("inet_ntop");
		exit(1);
	}
	fprintf(stderr, "客户端%s:%d连接成功\n"
      ,ip,ntohs(cin.sin_port));

	 /*创建线程用于通信*/
	pthread_create(&tid,NULL,
		(void *)cli_data_handle,(void*)&info);
	 

	}
 
	close(fd);
	return 0;
}

void cli_data_handle(void * arg){
	//分离线程
	pthread_detach(pthread_self());
	struct my_t pinfo = *((struct my_t*)arg);
	int ret ;
	char kbuf[BUFSIZ]={};
			strcpy(kbuf,">>>>>欢迎进入员工管理系统<<<<<\n**********************员工管理系统******************************\n请选择登录方式:1->管理员登录   2->用户登录  3->注册   quit->退出\n");
			sendto_client(kbuf,pinfo);
		while(1){
			/**********************员工管理系统**************************/

			recvto_client(kbuf,pinfo);
			switch(kbuf[0]){
				case 1:
					strcpy(kbuf,"管理员登录\n请输入你的帐号和密码\n");		
					sendto_client(kbuf,pinfo);
					break;
				case 2:

					break;
				case 3:
		
					break;
				default:
					strcpy(kbuf,"输入格式错误请重新输入:");
					sendto_client(kbuf,pinfo);
					continue;

			}
	}
	
	close(pinfo.newfd);
}

//参数 发送的消息buf,my_t info 
void  sendto_client(char *buf,struct my_t cinfo){
	int ret;
	char kbuf[BUFSIZ];
	
	strcpy(kbuf,buf);
	printf("%s\n",kbuf);
	struct my_t pinfo = cinfo;
	do{                                                                                                                                                                                                                                
		ret = send(pinfo.newfd,kbuf,strlen(kbuf),0);
	}while(ret<0 && EINTR == errno);

	if(ret<0) {
		perror("send");
		exit(5);
	} else if(!ret) {
		fprintf(stderr, "对方正常关闭\n");
		exit(6);
	}   

	if (!strncasecmp(kbuf,QUIT,strlen(QUIT))) {
		fprintf(stderr, "客户端已退出\n");
		exit(7);
	}   
	 bzero(kbuf,BUFSIZ);
}

//接受一次客户端的消息

void recvto_client(char *buf,struct my_t cinfo)
{
	bzero(buf,sizeof(buf));
	struct my_t pinfo = cinfo;
	int ret;
		//接受客户端传来的信息
		do{
			ret = recv(pinfo.newfd,buf,
				sizeof(buf),0);
				}while(ret<0&&EINTR == errno);
		if(ret<0) {
			perror("recv");
		} else if(!ret) {
		fprintf(stderr, "对方正常关闭\n");
			}
		//客户端直接退出
		if (!strncasecmp(buf,QUIT,strlen(QUIT))) {
      fprintf(stderr, "客户端(%s:%d)已退出\n",inet_ntoa(pinfo.cin.sin_addr),ntohs(pinfo.cin.sin_port));
	  fprintf(stderr, "客户端(%s-%d):%s",
			  inet_ntoa(pinfo.cin.sin_addr),
			  ntohs(pinfo.cin.sin_port),buf);
		}
}







